import { randomString, FormatTemplate } from 'pub-bbx-utils';
import Field from '@src/model/Field';
import { isSelect, isMultiSelect, isCascader, isHaveDefaultValueCascader } from './util';
import * as FormInfoConfig from './components/FormInfo/config';
import { getCommonDefaultLangForKey, formatLanguage, initOptionLanguage, setOldDefaultLang, getDefaultLangOpts } from '@src/component/util/multiLang/index';

import { toFormField, toField, isDateField, isDatetimeField } from './util'
import { isEmpty, isFalsy, isObject } from '@src/util/type'
import locales, { t } from '@src/locales'
import { getMainLanguageKey } from '@hooks/useFormMultiLanguage'
import _ from 'lodash';

import { FieldTypeMappingEnum } from '@model/enum/FieldMappingEnum';

/** 补全formType 为select时的所需字段 */
function fillPropForSelect(params){
  let setting = params.setting || {};
  
  let options = [];
  let isMulti = false;
  let dependencies = setting.dependencies || {};
  
  if(isSelect(params) || isMultiSelect(params)){
    
    let dataSource = setting.dataSource || [];
    const dataSourceLanguage = params?.setting?.dataSourceLanguage
    const currLangDataSource = dataSourceLanguage?.[locales.locale] || []
    // 【产品类型】【质保规则】小地球设置不生效, 看代码别的地方应该也存在这种问题, 但没有得到反馈, 先只修改【质保规则】一个字段
    // 接上述，目前dataSource存在被服务端替换为当前语言对应的情况，所以在没有值的语言下编辑时，小地球数据会为空，所以改下判断
    // 无法确定dataSource是不是都替换为当前语言了，所以还是判断下
    if(!dataSource.length && currLangDataSource.length) {
      dataSource = currLangDataSource
    }
    // 如果当前语言没值，就循环确认下其他语言有没有值
    if(!dataSource.length && dataSourceLanguage) {
      for(let langValue of Object.values(dataSourceLanguage)) {
        // 其他语言就算有值也默认用空字符，主要确保选项数量就行，应该是没什么问题，如果有问题再确认~
        if(langValue?.length) dataSource = langValue.map(() => '')
      }
    }
    let initDefault = false;
    
    isMulti = setting.isMulti === true;
    options = dataSource.map(value => {
      let isDefault = false;
      // 只有第一个默认值生效
      if(!initDefault && value == params.defaultValue){
        isDefault = true;
        initDefault = true;
      }
      
      return {value, isDefault};
    })

    // 下拉菜单多语言
    if (!isEmpty(setting.dataSourceLanguage)) {
      options = initOptionLanguage(setting.dataSourceLanguage, options)
    } else {
      const mainLa = getMainLanguageKey()
      options.forEach(opt => {
        opt.language = { ...getCommonDefaultLangForKey(), [locales.locale]: opt.value, [mainLa]: opt.value };
      });
    }

    // 没有选项，添加默认项
    if(options.length == 0) {
      // 优先级
      if(params.formType == 'level') {
        options.push(
          {value: '中', isDefault: false, language:{...getCommonDefaultLangForKey('common.base.middle'), [locales.locale]: t('common.base.middle')}
        }, {
          value: '低', isDefault: false, language:{...getCommonDefaultLangForKey('common.base.low'), [locales.locale]: t('common.base.low')}
        }, {
          value: '高', isDefault: false, language:{...getCommonDefaultLangForKey('common.base.high'), [locales.locale]: t('common.base.high')}
        });
      }
      // 服务内容
      else if(params.formType == 'serviceType') {
        options.push({
          value: '保内免费',
          isDefault: false,
          language: getCommonDefaultLangForKey('common.form.design.serviceType.value1')
        },
        {
          value: '保内收费',
          isDefault: false,
          language: getCommonDefaultLangForKey('common.form.design.serviceType.value2')
        }, {
          value: '保外免费',
          isDefault: false,
          language: getCommonDefaultLangForKey('common.form.design.serviceType.value3')
        }, {
          value: '保外收费',
          isDefault: false,
          language: getCommonDefaultLangForKey('common.form.design.serviceType.value4')
        });
      }
      // 服务类型
      else if(params.formType == 'serviceContent') {
        options.push({
          value: '安装',
          isDefault: false,
          language: getCommonDefaultLangForKey('common.form.design.serviceContent.value1')
        }, {
          value: '维修',
          isDefault: false,
          language: getCommonDefaultLangForKey('common.form.design.serviceContent.value2')
        }, {
          value: '保养',
          isDefault: false,
          language: getCommonDefaultLangForKey('common.form.design.serviceContent.value3')
        }, {
          value: '巡检',
          isDefault: false,
          language: getCommonDefaultLangForKey('common.form.design.serviceContent.value4')
        }, {
          value: '检查',
          isDefault: false,
          language: getCommonDefaultLangForKey('common.form.design.serviceContent.value5')
        });
      }
      else { 
        options.push({value: '', isDefault: false, language: {}}, {value: '', isDefault: false, language: {}}, {value: '', isDefault: false, language: {}});
      }
    }
    
  }
  return {options, isMulti, dependencies};
}

/**
 * 用于表单设计的字段类
 * 后端给出的字段数据需要调用 util.toFormField 转换成该格式
 * 
 * @author dongls 
 */
export default class FormField{
  /** 
   * 默认构造函数
   * @param {object} params - 构造函数参数
   * @param {string} params.formType - 字段类型
   * @param {string} params.displayName - 字段名称
   */
  constructor(params = {}){
    // 国际化相关
    setOldDefaultLang(params)
    Object.keys(params).forEach(key => {
      this[key] = params[key];
    })

    // 旧字段没有id字段，而是使用fieldId替代
    this.id = params.id || params.fieldId;
    // 前端生成fieldName
    this.fieldName = params.fieldName || `field_${randomString(16)}`;
    // 字段类型
    this.formType = params.formType; 
    this.displayName = params.displayNameLanguage?.[locales.locale] || params.displayName || t('common.base.title');
    this.displayNameLanguage = params.displayNameLanguage;
    this.defaultValueLanguage = params?.defaultValueLanguage || null;
    this.placeHolderLanguage = params.placeHolderLanguage;
    // 是否必填   0 - 必填，1 - 非必填
    this.isNull = typeof params.isNull == 'number' ? params.isNull : 1; 

    this.fieldMappingForm = params.fieldMappingForm || {};
    // 是否允许搜索 0 - 不允许，1 - 允许
    this.isSearch = typeof params.isSearch == 'number' ? params.isSearch : 0; 
    this.placeHolder = params.placeHolderLanguage?.[locales.locale] || params.placeHolder || ''; // 提示信息
    this.defaultValue = params.defaultValueLanguage?.[locales.locale] || params.defaultValue; // 默认值
    // 是否为系统字段 0 - 非系统字段，1 - 系统字段
    this.isSystem = typeof params.isSystem == 'number' ? params.isSystem : 0;
    this.registerFieldFlag = typeof params.registerFieldFlag == 'boolean' ? params.registerFieldFlag : false;
    
    // 产品注册。是否为产品注册标识
    this.isRegister = typeof params.isRegister == 'number' ? params.isRegister : 0;
    // 工单专属字段： 是否在移动端显示 0 - 不显示，1 - 显示
    this.isAppShow = typeof params.isAppShow == 'number' ? params.isAppShow : 0;
    // 是否隐藏   1 - 隐藏，0 - 不隐藏
    this.isHidden = typeof params.isHidden == 'number' ? params.isHidden : 0; 
    // 工单专属字段：是否是公用字段 1 - 是，0 - 否
    this.isCommon = typeof params.isCommon == 'number' ? params.isCommon : 0;
    // 公用字段: 1.设为公用字段设置 2.需判断是否是升级为公用字段而非拖拽进来的公共字段 而不能直接用isCommon
    this.isPublic = this.isCommon;
    // 是否是拖拽进来的公共字段 0 - 不是，1 - 是
    this.isDragCommon = typeof params.isDragCommon == 'number' ? params.isDragCommon : 0;
    // 是否曾经是公共字段 0 - 不是，1 - 是
    this.isOnceCommon = typeof params.isOnceCommon == 'number' ? params.isOnceCommon : 0;
    // 是否对客户可见（自主门户）   1 - 可见，0 - 不可见
    this.isShow = typeof params.isShow == 'number' ? params.isShow : 0; 
    // 针对事件类型的表单控件做的处理,如果是分割线控件或者是说明信息控件 并且params不存isShow属性 则默认选中 是否对客户可见 
    if((params.formType === 'separator' || params.formType === 'info') && !params.hasOwnProperty('isShow')){
      this.isShow = 1
    }
    // formType 为select时需要补全一下字段
    let {options, isMulti, dependencies} = fillPropForSelect(params)
    this.options = options; // 下拉菜单类型选项
    this.isMulti = isMulti; // 是否为多选
    this.dependencies = dependencies; // 逻辑显示项用
    // 质保信息默认值设置，因为有选择审批相关，不给默认值直接赋值给setting会报错
    if(params.formType == 'quality' && JSON.stringify(params.setting) == '{}') {
      this.setting = {
        defaultQuality: 'IN',
        allowProduct: 0,
        approveRule: {
          multiApproveSetting: [
            {
              state: '',
              leader: '',
              approves: [],
              level: '',
              taskTemplateId: ''
            }
          ],
          state: '',
          leader: '',
          approves: [],
          level: '',
          taskTemplateId: ''
        }
      }
    }else {
      this.setting = params.setting || {};
    }

    // 故障库默认值
    if(params.fieldName === 'faultLibrary' && JSON.stringify(params.setting) == '{}') {
      this.setting.faultLibraryOption = {
        productType: true,
        faultScene: true,
        faultDetails: true,
        faultReason: true,
        solution: true,
        budgetAmount: true
      }
    } else {
      this.setting = params.setting || {}
    }

    this.defaultTips = this.setting.autoGeneration ? `${params.displayName}${t('common.form.preview.text.des7')}` : ''

    // // 处理客户地址
    if (this.fieldName === 'customerAddress' && this.isSystem && !params.setting.customerAddressConfig) {
      this.setting.customerAddressConfig = {};
    }
    
    this.cascaderDefaultValue = { maxDeep: 2, dataSource:[{value:`${t('common.base.levelOption', {data1: t('common.base.number1')})} 1`, children:[{ value : `${t('common.base.levelOption', {data1: t('common.base.number2')})} 1`}]}], checkStrictly: false}

    if (this.setting.dataSourceLanguage) {
      this.cascaderDefaultValue.dataSourceLanguage = this.setting.dataSourceLanguage
    } else {
      const dataSourceLanguage = getDefaultLangOpts()
      if (this.setting.dataSource?.length) {
        const manLa = getMainLanguageKey()
        this.cascaderDefaultValue.dataSourceLanguage = {
          ...dataSourceLanguage,
          [manLa]: _.cloneDeep(this.setting.dataSource),
          [locales.locale]: _.cloneDeep(this.setting.dataSource)
        }
      } else {
        this.cascaderDefaultValue.dataSourceLanguage = {
          ...dataSourceLanguage,
          [locales.locale]: this.cascaderDefaultValue.dataSource
        }
      }
    }

    // 多级菜单设置默认项
    if(isCascader(params)){
      this.setting = this.cascaderDefaultValue
    }

    if (isHaveDefaultValueCascader(params)) {
      if (!(params.setting?.dataSource?.length > 0)) {
        this.setting = this.cascaderDefaultValue
      }
    }

    if(params.formType === 'currency' && !params.setting.defaultCurrency) {
      this.setting.defaultCurrency = 'CNY';
    }

    // 计算公式
    if (params.formType === 'formula') {
      if(isEmpty(params.setting)) {
        this.setting = { checkCurrency: 1 };
      } else {
        this.setting.checkCurrency = this.setting?.checkCurrency ?? 1;
      }
    }

    // 辅助字段
    this.dragging = false; // 当前字段时候正在被拖拽

    // 子表单相关
    // params.isChildForm = params.isChildForm || 0
    if (params.subFormFieldList) {
      params.subFormFieldList.forEach(v => {
        v.parentFieldId = this.fieldName
      })
      this.subFormFieldList = toFormField(params.subFormFieldList)
    }
    if (params.parentFieldId) {
      this.parentFieldId = params.parentFieldId
    }

    if(params.isSubForm) {
      let setting = this.setting || {}
      setting.isSubForm = params.isSubForm
      this.setting = setting
    }
    // 服务商专属字段：系统字段是否显示必填
    this.showIsNull = params.showIsNull;
  }

  /** @deprecated 兼容旧有写法*/
  get _id(){
    return this.fieldName;
  }

  /** 从Filed构建为组件可接受的字段 */
  static fromField(field){ 
    // 连接器
    if (field.formType === FieldTypeMappingEnum.Connector) {
      field.subFormFieldList = (field?.setting.subFormFieldList || []).map(f => this.fromField(f));
      field.setting.subFormFieldList = field.subFormFieldList
    }
    
    return new FormField(field);
  }

  /** 将字段转换成后端可接收的字段 */
  static toField(field){
    const manLa = getMainLanguageKey()
    let option = {};

    option.id = field.id;
    option.fieldName = field.fieldName;
    option.formType = field.formType;
    // 在表单设计阶段不修改原有客户主语言的内容
    option.displayName = field.displayNameLanguage?.[manLa] || field.displayName;
    option.displayNameLanguage = field.displayNameLanguage;
    option.defaultValueLanguage = field?.defaultValueLanguage || null;
    option.isNull = field.isNull;
    option.isSearch = field.isSearch;
    option.placeHolder = field.placeHolderLanguage?.[manLa] || field.placeHolder;
    option.placeHolderLanguage = field.placeHolderLanguage;
    option.isSystem = field.isSystem;
    option.isAppShow = field.isAppShow;
    option.isHidden = field.isHidden;
    option.isCommon = field.isCommon;
    option.isPublic = field.isPublic;
    option.isRegister = field.isRegister;
    option.isDragCommon = field.isDragCommon;
    option.isOnceCommon = field.isOnceCommon;
    option.fieldMappingForm = field.fieldMappingForm;
    option.isShow = field.isShow;
    option.orderId = field.orderId;
    option.tableName = field.tableName
    if (field.subFormFieldList) {
      option.subFormFieldList = toField(field.subFormFieldList)
    }

    if (field.parentFieldId) {
      option.parentFieldId = field.parentFieldId
    }

    option.showIsNull = field.showIsNull;
    
    const formType = field.formType;
    let setting = {};
    let defaultValue = null;

    // 处理下拉选项
    if(isSelect(field) || isMultiSelect(field)){
      let dataSource = [];
      let opts = field.options || [];
      for(let i = 0; i < opts.length; i++){
        let opt = opts[i];
        dataSource.push(opt.value);
        // 只有第一个默认值生效
        if(opt.isDefault && !defaultValue) {
          defaultValue = opt.value;
          if(field.formType === 'solveStatus'){
            defaultValue = opt.value.text; // 服务备注解决状态的值不一样 这里重新处理
          }
        }
      }
      let dataSourceLanguage = formatLanguage(field.options)
      // fix: 28780，因为下面dataSource优先取的是dataSourceLanguage?.[manLa]，而这个值可能为空数组，与dataSource的数量对不上，
      // 所以加下逻辑，如果数量对不上，当前为主语言时，直接取dataSource，如果不是，就通过dataSource补齐选项数量，确保校验
      if(dataSource?.length && dataSourceLanguage && dataSource?.length !== dataSourceLanguage[manLa]?.length) {
        dataSourceLanguage[manLa] = manLa === locales.locale ? dataSource : dataSource.map((v, i) => dataSourceLanguage[manLa]?.[i] || '')
      }
      field.formType == 'select' && (setting.isMulti = field.isMulti ?? field.setting?.isMulti );
      setting.dataSource = dataSourceLanguage?.[manLa] || dataSource;
      setting.dataSourceLanguage = dataSourceLanguage;
    }

    if(field.formType === 'info') {
      option.placeHolder = option.placeHolder || FormInfoConfig.PLACE_HOLDER;
    }

    if(['cascader','text','textarea','number','estimatedMileage','actualMileage','taskEstimatedMileage', 'currency'].includes(field.formType)) {
      defaultValue = field.defaultValueLanguage?.[manLa] || field.defaultValue;
    }

    if (field.setting) {
      setting = {
        ...field.setting,
        ...setting,
      }
    }
    
    // 过滤空白依赖
    let dependencies = field.dependencies || {};
    Object.keys(dependencies).forEach(prop => {
      let dep = dependencies[prop];
      if(!Array.isArray(dep) || dep.length == 0) {
        delete dependencies[prop]
      }
    })
    
    if(Object.keys(dependencies).length > 0) {
      setting.dependencies = dependencies;
    } else {
      delete setting.dependencies
    }
    
    if (formType == 'connector') {
      
      const connector = setting?.connector || {};
      const showFieldNameList = connector?.showFieldNameList || [];
      const toFieldList = connector?.toFieldList || [];

      setting.subFormFieldList = (field?.subFormFieldList || []).map(f => this.toField(f));
      
      toFieldList.forEach(toField => {
        
        const enName = toField?.enName || ''
        
        toField.show = showFieldNameList.includes(enName)
        
      })
    }
    
    this.dateHandler(field, setting)
    
    option.setting = setting;
    option.defaultValue = defaultValue;

    return new Field(option);
  }
  
  static dateHandler(field, setting) {
    // 处理 日期和日期时间字段
    const isDateOrDatetime = isDateField(field) || isDatetimeField(field);
    if (isDateOrDatetime && isObject(field.setting)) {
      setting.isDateHour = false
      // 日期类型
      const dateType = field.setting.dateType;
      // 没有日期类型的字段不处理
      if (isFalsy(dateType)) {
        return
      }
      
      // 是否为年月日时的格式
      const isDateHour = dateType.toUpperCase() === FormatTemplate.dateHour.toUpperCase();
      if (isFalsy(isDateHour)) {
        return
      }
      
      // 日期时间格式
      const newDateType = 'yyyy-MM-dd HH:mm'
      setting.dateType = newDateType
      setting.isDateHour = isDateHour
      
    }
  }
  
}